#!/bin/sh -x


# TODO - clean up code - move existence tests to the change permissions/owner/group functions.
# TODO - write a fix bundle function which takes args for the permission of the executable.
# TODO - validate arguments
# TODO - generate .sh file which is sourced to define names and locations of all apps.

# ----------------------------------------------------------------------------
#
# Take $1 $2 and $3 and convert to
# 	PACKAGE_NAME, VARIANT, VOLUME, and INSTALLER_TOOLS_DIR
#	$1 is expected to be the full path to the installer .pkg
#
#
function processPreflightArgs()
{
	P="$1"
	PACKAGE_NAME=`/usr/bin/basename "${P}" .pkg`
	VARIANT=${PACKAGE_NAME#*-}
	if [ "${VARIANT}" = "${PACKAGE_NAME}" ]
	then
		VARIANT=""
	else
		VARIANT="-${VARIANT}"
	fi
	
	INSTALLER_TOOLS_DIR="$1/Contents/Resources"
}

# ----------------------------------------------------------------------------
#
# Take $1 $2 and $3 and convert to
# 	PACKAGE_NAME, VARIANT, VOLUME, and INSTALLER_TOOLS_DIR
#	$1 is expected to be the full path to the installer .pkg
#
#
function processPostflightArgs()
{
	P="$1"
	PACKAGE_NAME=`/usr/bin/basename "${P}" .pkg`
	
	// Extract the Variant from the package name
	VARIANT=""
	if [ "${PACKAGE_NAME}" != "${PACKAGE_NAME%-Log}" ]
	then
		VARIANT="-Logging"
	
	elif [ "${PACKAGE_NAME}" != "${PACKAGE_NAME%-Dbg}" ]
	then
		VARIANT="-Debug"
	fi
		
	# Determine the Destination Volume
	
	VOLUME=$3
	if [ "${VOLUME}" = "/" ]
	then
		VOLUME=""
	fi
	
	INSTALLER_TOOLS_DIR="$1/Contents/Resources"
}

# ----------------------------------------------------------------------------

function bailOnError()
{
	if test "$1" -ne 0; then
		exit 1
	fi
}

# ----------------------------------------------------------------------------

function showInstallerState()
{
	echo "  "
	echo "-------------------------------------------------------------"
	echo "$1"
	echo "  "
	echo "  "
}

# Functions to conveniently set
# 	user, group, and permissions

# ----------------------------------------------------------------------------
# fixPermissions group <permissions> <filename>
function fixPermissions()
{
	set -x
	/bin/chmod "$2" "$3"
	/usr/bin/chgrp "$1" "$3"
	set +x
}

# ----------------------------------------------------------------------------
# recurseFixPermissions <group> <permissions> <filename>
function recurseFixPermissions()
{
	set -x
	/bin/chmod     -R "$2" "$3"
	/usr/bin/chgrp -R "$1" "$3"
	set +x
}

# ----------------------------------------------------------------------------
# recurseFixOwnership group user filename
function recurseFixOwnership()
{
	set -x
	sudo /usr/sbin/chown -R "$2" "$3"
	sudo /usr/bin/chgrp  -R "$1" "$3"
	set +x
}

# ----------------------------------------------------------------------------
# exit script with error if symbol named $2 with value $1 doesn't exist as a file
# system object.
# TODO - disable and restore echoing during these functions
function assertExistFileSystemObject()
{
	# if name is ''
	if [ "x$1" == "x" ]
	then
		echo $2 "is undefined"
		exit 1
	fi
	# if name exists
	if ! [ -e "$1" ]
	then
		echo $2 " == " $1 " doesn't exist"
		exit 1
	fi
}

# ----------------------------------------------------------------------------
# exit script with error if symbol $2 with value $1 doesn't exist or isn't a directory
function assertExistDir()
{
	assertExistFileSystemObject "$1" "$2"
	# if name is dir
	if ! [ -d "$1" ]
	then
		echo $2 " == " $1 " is not a directory"
		exit 1
	fi
}

# ----------------------------------------------------------------------------
# exit script with error if symbol $2 with value $1 doesn't exist or isn't a directory
function assertDefinedString()
{
	if  [ -z "$1" ]
	then
		echo $2 " == " $1 " is not a file"
		exit 1
	fi
}

# ----------------------------------------------------------------------------
# exit script with error if symbol $2 with value $1 doesn't exist or isn't a directory
function assertExistFile()
{
	assertExistFileSystemObject "$1" "$2"
	# if name is file
	if ! [ -f "$1" ]
	then
		echo $2 " == " $1 " is not a file"
		exit 1
	fi
}

# ----------------------------------------------------------------------------
# exit script with error if symbol $2 with value $1 doesn't exist or isn't an executable
function assertExistExecutable()
{
	assertExistFileSystemObject "$1" "$2"
	# if name is executable
	if ! [ -x "$1" ]
	then
		echo $2 " == " $1 " is not executable"
		exit 1
	fi
}

# ----------------------------------------------------------------------------
# exit script with error if symbol $2 with value $1 doesn't exist or isn't a directory
function assertExistAppBundle()
{
	assertExistDir  "$1"						"$2"
	assertExistDir  "$1/Contents"				"$2/Contents"
	assertExistDir  "$1/Contents/Resources"		"$2/Resources"
	assertExistDir  "$1/Contents/MacOS"			"$2/MacOS"
	assertExistFile "$1/Contents/Info.plist"	"$2/Contents/Info.plist"
	assertExistFile "$1/Contents/PkgInfo"		"$2/Contents/PkgInfo"
}

# ----------------------------------------------------------------------------
function moveToTrash()
{
	__TRASH_ITEM__="$1"
	if [ -e "${__TRASH_ITEM__}" ]
	then
		assertExistExecutable  "${INSTALLER_TOOLS_DIR}/MoveToTrash" "-MoveToTrash-"
		# TODO - MoveToTrash >might< need seduid permission bit set.
		set -x
		"${INSTALLER_TOOLS_DIR}/MoveToTrash" "${__TRASH_ITEM__}"
		set +x
	fi
}

# ----------------------------------------------------------------------------
function moveVariantsToTrash()
{
	moveToTrash "$1$2"
	moveToTrash "$1-Debug$2"
	moveToTrash "$1-Logging$2"
}

# ----------------------------------------------------------------------------
# defineInstallLocations
# 	expects VOLUME to be defined
#
#	defines the following directories
#		APPLICATION_SUPPORT_DIR
#		APPLICATION_SUPPORT_BIN_DIR
#		APPLICATION_DIR
#		COMPONENTS_DIR
#		SYSTEM_EXTENSIONS_DIR
#		STARTUP_ITEMS
#		SYSTEM_STARTUP_ITEMS
#

function defineInstallLocations()
{
	VENDOR_SUBDIR="$1"
	VENDOR_APP_SUBDIR="$2"
	APPLICATION_SUPPORT_DIR="${VOLUME}/Library/Application Support/${VENDOR_SUBDIR}"
	APPLICATION_SUPPORT_BIN_DIR="${APPLICATION_SUPPORT_DIR}/Private"
	APPLICATION_DIR="${VOLUME}/Applications/${VENDOR_APP_SUBDIR}"
	COMPONENTS_DIR="${VOLUME}/Library/Components"
	SYSTEM_EXTENSIONS_DIR="${VOLUME}/System/Extensions"
	STARTUP_ITEMS="${VOLUME}/Library/StartupItems"
	SYSTEM_STARTUP_ITEMS="${VOLUME}/System/Library/StartupItems"
}


# ----------------------------------------------------------------------------

function fixBasicDirectoryPermissions()
{
	assertExistDir  "${VOLUME}/Library"						"-Library-"
	assertExistDir  "${VOLUME}/Library/Components"			"-Library/Components-"
	assertExistDir  "${VOLUME}/Library/Application Support" "-Library/Application Support-"
	
	fixPermissions         admin 775  "${VOLUME}/Library"
	fixPermissions         admin 775  "${VOLUME}/Library/Components"
	fixPermissions         admin 775  "${VOLUME}/Library/Application Support"
}


# ----------------------------------------------------------------------------
# Fixes permissions for various directories
#   Shouldn't be necessary except for perhaps support and device keys.

function fixDirectoryPermissions()
{
	showInstallerState "Fixing Directory Permissions"
	
	assertExistDir  "${APPLICATION_SUPPORT_DIR}" "APPLICATION_SUPPORT_DIR"
	assertExistDir  "${APPLICATION_SUPPORT_DIR}/Device Keys" "-Device Keys Dir-"
	assertExistDir  "${APPLICATION_SUPPORT_BIN_DIR}" "-Application Support Bin Dir-"
	
	fixBasicDirectoryPermissions
	fixPermissions         admin 775  "${APPLICATION_SUPPORT_DIR}"
	fixPermissions		   admin 775  "${APPLICATION_SUPPORT_DIR}/Device Keys"
	fixPermissions		   admin 775  "${APPLICATION_SUPPORT_BIN_DIR}"
}

# ----------------------------------------------------------------------------
function prepareCameraControl()
{
	showInstallerState "Preparing Camera Control"
	
	if [ -z "${CAMERA_CONTROL_APP}" ]
	then
		CAMERA_CONTROL_APP="${APPLICATION_DIR}/IOXperts Camera Control${VARIANT}.app"
	fi
	
	assertExistAppBundle  "${CAMERA_CONTROL_APP}" "-Camera Control App-"
	
	recurseFixPermissions  admin 755  "${CAMERA_CONTROL_APP}"
}

# ----------------------------------------------------------------------------
function removeCameraControl()
{
	moveVariantsToTrash "${APPLICATION_DIR}/IOXperts Camera Control" ".app"
}

# ----------------------------------------------------------------------------
function killDeviceMonitor()
{
	assertExistExecutable  "${INSTALLER_TOOLS_DIR}/KillDeviceMonitor" "-KillDeviceMonitor-"
	"${INSTALLER_TOOLS_DIR}/KillDeviceMonitor"
}

# ----------------------------------------------------------------------------
function removeDeviceMonitors()
{
	DEVICE_MONITOR="${STARTUP_ITEMS}/IOXpertsDeviceMonitor"
	SYSTEM_DEVICE_MONITOR="${SYSTEM_STARTUP_ITEMS}/IOXpertsDeviceMonitor"

	moveToTrash "${DEVICE_MONITOR}"
	moveToTrash "${SYSTEM_DEVICE_MONITOR}"
}

# ----------------------------------------------------------------------------
function prepareDeviceMonitor()
{
	showInstallerState "Preparing Device Monitor"
	
	if [[ -z "${DEVICE_MONITOR}" && -z "${DEVICE_MONITOR_APP}" ]]
	then
		DEVICE_MONITOR="${STARTUP_ITEMS}/IOXpertsDeviceMonitor"
		DEVICE_MONITOR_APP="${DEVICE_MONITOR}/ioxdeviced${VARIANT}.app"
		DEVICE_MONITOR_EXECUTABLE="${DEVICE_MONITOR_APP}/Contents/MacOS/ioxdeviced${VARIANT}"
	else
		assertDefinedString "${DEVICE_MONITOR}" "-DEVICE_MONITOR-"
		assertDefinedString "${DEVICE_MONITOR_APP}" "-DEVICE_MONITOR_APP-"
		# local exe=`basename -s ".app" "${DEVICE_MONITOR_APP}"`
		local exe=`basename "${DEVICE_MONITOR_APP}" ".app"`
		echo "basename ${exe}"
		#exe=`echo ${exe} | sed -e 's/\.app$//'`
		#echo "pDM() - no ext ${exe}"
		assertDefinedString "${exe}"  "-exe-"
		DEVICE_MONITOR_EXECUTABLE="${DEVICE_MONITOR_APP}/Contents/MacOS/${exe}"
	fi
	local DEVICE_MONITOR_LAUNCH_EXECUTABLE="${DEVICE_MONITOR_APP}/Contents/Resources/Launcher"
	
	assertExistDir						"${DEVICE_MONITOR}"				"DEVICE_MONITOR"
	assertExistAppBundle				"${DEVICE_MONITOR_APP}"			"DEVICE_MONITOR_APP"
	assertExistExecutable				"${DEVICE_MONITOR_EXECUTABLE}"  "DEVICE_MONITOR_EXECUTABLE"
	assertExistExecutable				"${DEVICE_MONITOR_LAUNCH_EXECUTABLE}"			"DEVICE_MONITOR_LAUNCH_EXECUTABLE"
	
	recurseFixPermissions  wheel 755	"${DEVICE_MONITOR}"
	# recurseFixOwnership    wheel nobody		"${DEVICE_MONITOR}"
	recurseFixOwnership   wheel root	"${DEVICE_MONITOR}"
	set -x
	/bin/chmod					6755	"${DEVICE_MONITOR_EXECUTABLE}"
	/bin/chmod                   664	"${DEVICE_MONITOR_APP}/Contents/Info.plist"
	/bin/chmod                   664    "${DEVICE_MONITOR_APP}/Contents/PkgInfo"
	/bin/chmod				    6755    "${DEVICE_MONITOR_LAUNCH_EXECUTABLE}"
	set +x
}

# ----------------------------------------------------------------------------
function prepareRegisterApp()
{
	showInstallerState "Preparing Registration App"
	
	if ! [ -z "${REGISTER_APP}" ]
	then
		local exe=`basename "${REGISTER_APP}" ".app"`
		echo "basename ${exe}"
		assertDefinedString "${exe}"  "-exe-"
		REGISTER_EXECUTABLE="${REGISTER_APP}/Contents/MacOS/${exe}"
		SNCREATE_EXECUTABLE="${REGISTER_APP}/Contents/Resources/SNCreate"
	else
		REGISTER_APP="${APPLICATION_SUPPORT_BIN_DIR}/IOXperts Register${VARIANT}.app"
		REGISTER_EXECUTABLE="${REGISTER_APP}/Contents/MacOS/IOXperts Register${VARIANT}"
		SNCREATE_EXECUTABLE="${REGISTER_APP}/Contents/Resources/SNCreate"
	fi
	
	assertExistAppBundle				"${REGISTER_APP}"				"REGISTER_APP"
	assertExistExecutable				"${REGISTER_EXECUTABLE}"		"REGISTER_EXECUTABLE"
	assertExistExecutable				"${SNCREATE_EXECUTABLE}"		"SNCREATE_EXECUTABLE"
	
	recurseFixPermissions  wheel 755	"${REGISTER_APP}"
	#recurseFixOwnership    wheel nobody   "${REGISTER_APP}"
	recurseFixOwnership    wheel root   "${REGISTER_APP}"
	set -x
	/bin/chmod                   664	"${REGISTER_APP}/Contents/Info.plist"
	/bin/chmod                   664	"${REGISTER_APP}/Contents/PkgInfo"

	/bin/chmod					6755	"${REGISTER_EXECUTABLE}"
	set +x

	recurseFixOwnership    wheel root   "${SNCREATE_EXECUTABLE}"
	set -x
	/bin/chmod                  2755	"${SNCREATE_EXECUTABLE}"
	set +x
}

# ----------------------------------------------------------------------------
function removeRegisterApp()
{
	moveVariantsToTrash  "${APPLICATION_SUPPORT_BIN_DIR}/IOXperts Register" ".app"
	moveVariantsToTrash  "${APPLICATION_SUPPORT_DIR}/IOXperts Register" ".app"
}

# ----------------------------------------------------------------------------
function prepareSessionMonitor()
{
	showInstallerState "Preparing Session Monitor"
	
	if ! [ -z "${SESSION_MONITOR_APP}" ]
	then
		# local exe=`basename -s ".app" "${SESSION_MONITOR_APP}"`
		local exe=`basename "${SESSION_MONITOR_APP}" ".app"`
		echo "basename ${exe}"
		assertDefinedString "${exe}"  "-exe-"
		SESSION_MONITOR_EXECUTABLE="${SESSION_MONITOR_APP}/Contents/MacOS/${exe}"
	else
		SESSION_MONITOR_APP="${APPLICATION_SUPPORT_BIN_DIR}/ioxsessiond${VARIANT}.app"
		SESSION_MONITOR_EXECUTABLE="${SESSION_MONITOR_APP}/Contents/MacOS/ioxsessiond${VARIANT}"
	fi
	
	assertExistAppBundle "${SESSION_MONITOR_APP}" "SESSION_MONITOR_APP"
	assertExistExecutable "${SESSION_MONITOR_EXECUTABLE}"  "SESSION_MONITOR_EXECUTABLE"
	
	recurseFixPermissions  wheel 755  "${SESSION_MONITOR_APP}"
	#recurseFixOwnership    wheel nobody   "${SESSION_MONITOR_APP}"
	recurseFixOwnership    wheel root "${SESSION_MONITOR_APP}"
	set -x
	/bin/chmod                   664  "${SESSION_MONITOR_APP}/Contents/Info.plist"
	/bin/chmod                   664  "${SESSION_MONITOR_APP}/Contents/PkgInfo"
	set +x
}

# ----------------------------------------------------------------------------
function removeSessionMonitor()
{
	moveVariantsToTrash "${APPLICATION_SUPPORT_BIN_DIR}/ioxsessiond" ".app"
	moveVariantsToTrash "${APPLICATION_SUPPORT_DIR}/ioxsessiond" ".app"
}

# ----------------------------------------------------------------------------
function prepareIdentifierApp()
{
	showInstallerState "Preparing Identifier App/Device Manager"
	
	if [ -z "${IDENTIFIER_APP}" ]
	then
		IDENTIFIER_APP="${APPLICATION_DIR}/Camera Identifier${VARIANT}.app"
	fi
	
	assertExistAppBundle "${IDENTIFIER_APP}" "IDENTIFIER_APP"
	recurseFixPermissions  wheel 755  "${IDENTIFIER_APP}"
	recurseFixOwnership   wheel root  "${IDENTIFIER_APP}"
	set -x
	/bin/chmod                   664  "${IDENTIFIER_APP}/Contents/Info.plist"
	/bin/chmod                   664  "${IDENTIFIER_APP}/Contents/PkgInfo"
	set +x
	# echo "${IDENTIFIER_APP}"
}

# ----------------------------------------------------------------------------
function removeIdentifierApp()
{
	moveVariantsToTrash "${APPLICATION_DIR}/Camera Identifier" ".app"
}

# ----------------------------------------------------------------------------
function prepareInstalledComponent()
{
	local COMPONENT="$1"
	local DEFAULT_BASE_NAME="$2"
	local DEFAULT_SUFFIX="$3"
	assertDefinedString "${DEFAULT_BASE_NAME}"  "-DEFAULT_BASE_NAME-"
	
	if [ -z "${DEFAULT_SUFFIX}" ]
	then
		DEFAULT_SUFFIX=".component"
	fi
	
	if [ -z "${COMPONENT}" ]
	then
		COMPONENT="${COMPONENTS_DIR}/${DEFAULT_BASE_NAME}${VARIANT}${DEFAULT_SUFFIX}"
	fi
	
	assertExistAppBundle              "${COMPONENT}"
	set -x
	/usr/bin/chgrp			-R admin  "${COMPONENT}"
	set +x

}

# ----------------------------------------------------------------------------
function removeKexts()
{
	# Remove the obsolete kexts
	moveToTrash "${SYSTEM_EXTENSIONS_DIR}/LogitechQuickCam.kext"
	moveToTrash "${SYSTEM_EXTENSIONS_DIR}/IOXpertsWebcam.kext"
}

# ----------------------------------------------------------------------------
function removeObsoleteLogitechComponents()
{
	# Remove the obsolete components
	# use only in logitech installer
	moveToTrash "${COMPONENTS_DIR}/Logitech QuickCam.component"
}

# ----------------------------------------------------------------------------
function repairQuickTime()
{
	showInstallerState "Reparing QuickTime"
	
	assertExistExecutable		"${INSTALLER_TOOLS_DIR}/qt6fix" "-qt6fix-"

	# Clean up bugs in QT 6.0, 6.1 and 6.2
	set -x
	/bin/chmod				     555  "${INSTALLER_TOOLS_DIR}/qt6fix"
	"${INSTALLER_TOOLS_DIR}/qt6fix"
	set +x
}

# ----------------------------------------------------------------------------
function registerDeviceMonitorWithLaunchServices()
{
	showInstallerState "Registering Device Monitor with Launch Services"
	
	assertExistExecutable		"${INSTALLER_TOOLS_DIR}/RegisterApps" "-RegisterApps-"

	# Record the locations of various components in com.ioxperts.common prefs.
	set -x
	/bin/chmod				     555  "${INSTALLER_TOOLS_DIR}/RegisterApps"
	"${INSTALLER_TOOLS_DIR}/RegisterApps" -m "${DEVICE_MONITOR_APP}"
	rv=$?
	set +x
	bailOnError ${rv}
}

# ----------------------------------------------------------------------------
function registerAppsWithLaunchServices()
{
	showInstallerState "Registering Applications with Launch Services"
	
	assertExistFileSystemObject "${DEVICE_MONITOR_APP}"		"DEVICE_MONITOR_APP"
	assertExistFileSystemObject "${REGISTER_APP}"			"REGISTER_APP"
	assertExistFileSystemObject "${SESSION_MONITOR_APP}"	"SESSION_MONITOR_APP"
	assertExistFileSystemObject "${IDENTIFIER_APP}"			"IDENTIFIER_APP"
	assertExistExecutable		"${INSTALLER_TOOLS_DIR}/RegisterApps" "-RegisterApps-"
	
	set -x
	/bin/chmod				     555  "${INSTALLER_TOOLS_DIR}/RegisterApps"
	"${INSTALLER_TOOLS_DIR}/RegisterApps"			 "${DEVICE_MONITOR_APP}" \
													 "${REGISTER_APP}" \
													 "${SESSION_MONITOR_APP}" \
													 "${IDENTIFIER_APP}"
	rv=$?
	set +x
	bailOnError ${rv}
}

# ----------------------------------------------------------------------------
# TODO - parameterize better
function registerDeviceMonitorAsGlobalLoginItem()
{
	local removalPat="ioxdeviced"
	if ! [ -z $1 ]
	then
		removalPat="$1"
	fi
	
	showInstallerState "Registering Device Monitor as Global Login Item"
	
	assertExistAppBundle  "${DEVICE_MONITOR_APP}" "-DeviceMonitor-"
	assertExistExecutable "${INSTALLER_TOOLS_DIR}/AddGlobalLoginItem" "-RegisterApps-"
	
	set -x
	/bin/chmod				     555  "${INSTALLER_TOOLS_DIR}/AddGlobalLoginItem"
	"${INSTALLER_TOOLS_DIR}/AddGlobalLoginItem"		"${DEVICE_MONITOR_APP}" "${removalPat}"
	rv=$?
	set +x
	bailOnError ${rv}
}

# ----------------------------------------------------------------------------
function registerSessionMonitorAsGlobalLoginItem()
{
	showInstallerState "Registering Session Monitor as Global Login Item"
	
	assertExistAppBundle  "${SESSION_MONITOR_APP}" "-SessionMonitor-"
	assertExistExecutable "${INSTALLER_TOOLS_DIR}/AddGlobalLoginItem" "-RegisterApps-"
	
	set -x
	/bin/chmod				     555  "${INSTALLER_TOOLS_DIR}/AddGlobalLoginItem"
	"${INSTALLER_TOOLS_DIR}/AddGlobalLoginItem"		"${SESSION_MONITOR_APP}" "ioxsessiond"
	rv=$?
	set +x
	bailOnError ${rv}
}

# ----------------------------------------------------------------------------
# If the SM can't launch Register after a clean install, consider
# adding this call to the postflight script.  It sets the prefs so the launch
# code for Register can find the Register app by full path.

function setAppLocationPreferences()
{
	showInstallerState "Setting Application Location Preferences"
	
	assertExistAppBundle  "${REGISTER_APP}" "-Registration App-"
	assertExistAppBundle  "${SESSION_MONITOR_APP}" "-Session Monitor App-"
	assertExistExecutable "${INSTALLER_TOOLS_DIR}/SetInstallationPrefs" "-SetInstallationPrefs-"
											
	set -x
	/bin/chmod				     555  "${INSTALLER_TOOLS_DIR}/SetInstallationPrefs"
	"${INSTALLER_TOOLS_DIR}/SetInstallationPrefs" -purchase "${REGISTER_APP}" \
												  -sessionMonitor "${SESSION_MONITOR_APP}"
	rv=$?
	set +x
	
	bailOnError ${rv}
}

# ----------------------------------------------------------------------------
function startDeviceMonitor()
{
	showInstallerState "Starting Device Monitor"
	
	assertExistExecutable "${INSTALLER_TOOLS_DIR}/Launcher" "-Launcher-"
	assertExistAppBundle "${DEVICE_MONITOR_APP}" "DEVICE_MONITOR_APP"

	# Start the Device Monitor
	# TODO - Require Reboot or logout/login 
	set -x
	"${INSTALLER_TOOLS_DIR}/Launcher" "${DEVICE_MONITOR_APP}"
	rv=$?
	set +x
	bailOnError ${rv}
	
	# TODO - add dialog - reboot?"yes":"no"
	#  if "no" - start device monitor
	#  if "yes" - reboot
}

# ----------------------------------------------------------------------------
function killSessionMonitor()
{
	showInstallerState "Stopping Session Monitor"
	
	assertExistExecutable "${INSTALLER_TOOLS_DIR}/KillSessionMonitor" "-KillSessionMonitor-"
	set -x
	"${INSTALLER_TOOLS_DIR}/KillSessionMonitor"
	set +x
}

# ----------------------------------------------------------------------------
function startSessionMonitor()
{
	showInstallerState "Starting Session Monitor"
	
	# assertExistExecutable "${SESSION_MONITOR_EXECUTABLE}" "SESSION_MONITOR_EXECUTABLE"
	assertExistExecutable "${INSTALLER_TOOLS_DIR}/Launcher" "-Launcher-"
	assertExistAppBundle "${SESSION_MONITOR_APP}" "SESSION_MONITOR_APP"

	# Start the Session Monitor
	# TODO - Require Reboot or logout/login 
	set -x
	"${INSTALLER_TOOLS_DIR}/Launcher" "${SESSION_MONITOR_APP}"
	set +x
	
	# TODO - bailOnError $?
}

# ----------------------------------------------------------------------------
function startIdentifierApp()
{
	showInstallerState "Starting Identifier"
	
	# assertExistExecutable "${SESSION_MONITOR_EXECUTABLE}" "SESSION_MONITOR_EXECUTABLE"
	assertExistExecutable "${INSTALLER_TOOLS_DIR}/Launcher" "-Launcher-"
	assertExistAppBundle "${IDENTIFIER_APP}" "IDENTIFIER_APP"

	# Start the Camera Identifier
	set -x
	sleep 3
	# sleep is a hack to make sure the SM and DM have time to launch.
	"${INSTALLER_TOOLS_DIR}/Launcher" "${IDENTIFIER_APP}"
	set +x
	
	# TODO - bailOnError $?
}

# ----------------------------------------------------------------------------
function uninstall()
{
	showInstallerState "Uninstalling...."

	assertExistDir		  "${INSTALLER_TOOLS_DIR}"
	assertExistExecutable "${INSTALLER_TOOLS_DIR}/MoveToTrash" "-MoveToTrash-"
	assertExistExecutable "${INSTALLER_TOOLS_DIR}/KillDeviceMonitor" "-KillDeviceMonitor-"
	assertExistExecutable "${INSTALLER_TOOLS_DIR}/KillSessionMonitor" "-KillSessionMonitor-"
	assertExistExecutable "${INSTALLER_TOOLS_DIR}/ComponentTool" "-ComponentTool-"
	assertExistFile		  "${INSTALLER_TOOLS_DIR}/IOXpertsUninstaller.sh" "-Uninstaller Script-"
	assertExistFile       "${INSTALLER_TOOLS_DIR}/UninstallerTools.sh" "-Uninstaller Tools-"

	set -x
	/bin/chmod				     555  "${INSTALLER_TOOLS_DIR}/IOXpertsUninstaller.sh"
	/bin/chmod				    2555  "${INSTALLER_TOOLS_DIR}/MoveToTrash"
	/bin/chmod				     555  "${INSTALLER_TOOLS_DIR}/KillDeviceMonitor"
	/bin/chmod				     555  "${INSTALLER_TOOLS_DIR}/KillSessionMonitor"
	/bin/chmod				     555  "${INSTALLER_TOOLS_DIR}/ComponentTool"
	set +x

	assertExistExecutable "${INSTALLER_TOOLS_DIR}/IOXpertsUninstaller.sh" "-Uninstaller Script-"
	
	set -x
	"${INSTALLER_TOOLS_DIR}/IOXpertsUninstaller.sh" trash \
													-bin "${INSTALLER_TOOLS_DIR}" \
													-scripts "${INSTALLER_TOOLS_DIR}" \
													-installer -verbose -removeinstaller -clearprefs \
													$1 $2 $3 $4 $5 $6 $7 $8 $9
	# # TRY ${@[@]} instead of $1...$9
	rv=$?  > /dev/null 2>&1
	set +x
	bailOnError ${rv}
}

# ----------------------------------------------------------------------------
# Prior to DM 1.1b54 (prefs version 2) - device monitor prefs can be corrupted
# by bugs in the DM.
# TODO - correct handling of MoveToTrash wrt 10.2 and consistent behavior in installer tools.

function upgradeOrRemoveDeviceMonitorPrefs()
{
	showInstallerState "Examining Device Monitor Preferences...."
	
	assertExistDir		  "${INSTALLER_TOOLS_DIR}"
	
	if [ -e "${INSTALLER_TOOLS_DIR}/DMPrefsTool" ]
	then
		set -x
		/bin/chmod				     555  "${INSTALLER_TOOLS_DIR}/DMPrefsTool"
		set +x
	fi

	if [ -x "${INSTALLER_TOOLS_DIR}/DMPrefsTool" ]
	then
		# Prior to this version - remove the DM preferences
		"${INSTALLER_TOOLS_DIR}/DMPrefsTool" -version "1.1b54" "2"
		local rv=$?
		echo "DMPrefsTool -version 1.1b54 2     returns ${rv}"
		if [ ${rv} -eq 0 ]
		then
			echo "Removing Device Monitor Preferences"
			/bin/rm -f "/Library/Preferences/com.ioxperts.devicemonitor.plist"
		fi
	fi
	echo " "
}

# ----------------------------------------------------------------------------
# TODO - add point release as well, maybe beta and build num?
# i.e. support not just X.Y bug X.Y.ZaW

function IsOSBefore()
{
	local testMajor=$1
	local testMinor=$2
	
	if [ -z "${testMajor}" ]
	then
		testMajor=0
	fi
	
	if [ -z "${testMinor}" ]
	then
		testMinor=0
	fi
	
	local IS_PRE=1
	if [ -x "/usr/bin/sw_vers" ]
	then
		local _V=`/usr/bin/sw_vers | grep ProductVersion | sed -e 's/ProductVersion:[^0-9]*//'`
		local maj=`echo ${_V} | sed -e 's/\..*//'`
		local min=`echo ${_V} | sed -e 's/[0-9]*\.//' -e 's/\..*//'`
		# echo V ${_V}
		# echo "MAJ '${maj}'"
		# echo "MIN '${min}'"

		if  [ ${maj} -gt ${testMajor} ]
		then
			IS_PRE=0
		elif [[ ${maj} -eq ${testMajor} && ${min} -ge ${testMinor} ]]
		then
			IS_PRE=0
		fi
	fi
	return ${IS_PRE}
}

